package service

import (
	"crypto/tls"
	"encoding/base64"
	"fmt"
	"io"
	"simple-mail/entity"
	"simple-mail/model"
	"strings"

	"github.com/cihub/seelog"
	"github.com/google/uuid"
	"gopkg.in/gomail.v2"
)

// MailService 发送邮件service
type MailService struct {
}

// getFileSetting 用于附件 []byte ==> gomail.FileSetting
func getFileSetting(img []byte) gomail.FileSetting {
	return gomail.SetCopyFunc(func(writer io.Writer) error {
		_, err := writer.Write(img)
		return err
	})
}

// SendMail 发送邮件
func (m *MailService) SendMail(request model.SendMailRequest, fromIp string) (sendSuccess bool, toUserMsg string) {
	// 根据accountId获取账号信息
	accountId := request.AccountID
	subject := request.Subject
	requestId := request.RequestID
	attachments := request.Attachments
	accountEntity := entity.AccountEntity{}
	accountEntity.FindByID(accountId)
	sendSuccess = false
	failReason := ""

	if nil != accountEntity.ID {
		// 已拿到邮箱账户信息
		dialer := gomail.NewDialer(*accountEntity.Host, *accountEntity.Port, *accountEntity.Username, *accountEntity.Password)
		dialer.TLSConfig = &tls.Config{InsecureSkipVerify: true}

		mail := gomail.NewMessage()
		mail.SetHeader("From", mail.FormatAddress(*accountEntity.From, request.From))
		mail.SetHeader("To", request.To...)
		mail.SetHeader("Cc", request.Cc...)
		mail.SetHeader("Bcc", request.Bcc...)
		mail.SetHeader("Subject", subject)
		mail.SetBody(request.ContentType, request.Body)

		skipSend := false

		// 附件
		for filename, content := range attachments {
			if len(filename) > 0 && len(content) > 0 {
				contentBytes, err := base64.StdEncoding.DecodeString(content)
				if nil == err {
					mail.Attach(filename, getFileSetting(contentBytes))
				} else {
					seelog.Errorf("解析附件失败,取消发送 requestId[%s]", requestId)
					failReason = "解析附件失败,请使用Base64编码"
					toUserMsg = failReason
					sendSuccess = false
					skipSend = true
					break
				}
			}
		}

		if !skipSend {
			err := dialer.DialAndSend(mail)
			if nil != err {
				_ = seelog.Error(fmt.Sprintf("邮件发送出错 requestId[%s] subject[%s] %s", requestId, subject, err.Error()))
				failReason = err.Error()
				toUserMsg = "邮件发送出错"
			} else {
				seelog.Info(fmt.Sprintf("邮件发送成功 requestId[%s] subject[%s]", requestId, subject))
				sendSuccess = true
			}
		}
	} else {
		seelog.Error("获取账户信息失败 requestId[%s] accountId[%s]", requestId, accountId)
		failReason = "获取账户信息失败"
		toUserMsg = "获取账户信息失败,请检查accountId"
	}

	// 存储邮件发送记录
	uuid := uuid.New().String()
	to := strings.Join(request.To, ",")
	cc := strings.Join(request.Cc, ",")
	bcc := strings.Join(request.Bcc, ",")

	mailLog := entity.MailLogEntity{
		ID:         &uuid,
		AccountID:  &accountId,
		From:       &request.From,
		To:         &to,
		Cc:         &cc,
		Bcc:        &bcc,
		Subject:    &subject,
		Body:       &request.Body,
		RequestID:  &requestId,
		Success:    sendSuccess,
		FailReason: &failReason,
	}
	mailLog.Create()
	return sendSuccess, toUserMsg
}
